// 观察者模式：定义了对象间一种一对多的依赖关系，当目标对象Subject发生改变时，所有依赖它的对象Observer都会得到通知。
function EventEmitter() {
	this.events = new Map();
}

// 需要实现的一些方法：
// addListener、removeListener、once、removeAllListeners、emit

// 模拟实现addlistener方法
const wrapCallback = (fn, once = false) => ({ callback: fn, once });
EventEmitter.prototype.addListener = function(type, fn, once = false) {
	const hanlder = this.events.get(type);
	if (!hanlder) {
		// 没有type绑定事件
		this.events.set(type, wrapCallback(fn, once));
	} else if (hanlder && typeof hanlder.callback === 'function') {
		// 目前type事件只有一个回调
		this.events.set(type, [ hanlder, wrapCallback(fn, once) ]);
	} else {
		// 目前type事件数>=2
		hanlder.push(wrapCallback(fn, once));
	}
};
// 模拟实现removeListener
EventEmitter.prototype.removeListener = function(type, listener) {
	const hanlder = this.events.get(type);
	if (!hanlder) return;
	if (!Array.isArray(this.events)) {
		if (hanlder.callback === listener.callback) this.events.delete(type);
		else return;
	}
	for (let i = 0; i < hanlder.length; i++) {
		const item = hanlder[i];
		if (item.callback === listener.callback) {
			hanlder.splice(i, 1);
			i--;
			if (hanlder.length === 1) {
				this.events.set(type, hanlder[0]);
			}
		}
	}
};
// 模拟实现once方法
EventEmitter.prototype.once = function(type, listener) {
	this.addListener(type, listener, true);
};
// 模拟实现emit方法
EventEmitter.prototype.emit = function(type, ...args) {
	const hanlder = this.events.get(type);
	if (!hanlder) return;
	if (Array.isArray(hanlder)) {
		hanlder.forEach((item) => {
			item.callback.apply(this, args);
			if (item.once) {
				this.removeListener(type, item);
			}
		});
	} else {
		hanlder.callback.apply(this, args);
		if (hanlder.once) {
			this.events.delete(type);
		}
	}
	return true;
};
EventEmitter.prototype.removeAllListeners = function(type) {
	const hanlder = this.events.get(type);
	if (!hanlder) return;
	this.events.delete(type);
};


class EventPubSub{
    constructor(){
        this.event = {};
    }
    //订阅
    on(type, callback){
        if(!this.event[type]){
           this.event[type] = [callback];
        }else{
            this.event[type].push(callback);
        }
    }
    //解除订阅
    off(type, callback){
        if(!this.event[type]){
            return;
        }
        this.event[type] = this.event[type].filter(item => {
            return item != callback;
        })
    }
    //发布
    emit(type, ...args){
        if(!this.event[type]){
            return;
        }
        this.event[type].forEach(callback => {
            callback.apply(this, args);
        })
    }
    //执行一次
    once(type, callback){
        function f(){
            callback();
            this.off(type, f);
        }
        this.on(type, f);
    }
}